#include <iostream>
#include <string>
#include <vector>
#include <semaphore.h>
#include <pthread.h>


template<typename T>
class RingQueue
{
private:
    void P(sem_t &sem)//申请信号量P操作
    {
        sem_wait(&sem);
    }
    void V(sem_t &sem)//发布信号量V操作
    {
        sem_post(&sem);
    }
    void Lock(pthread_mutex_t &mutex)//加锁
    {
        pthread_mutex_lock(&mutex);
    }
    void UnLock(pthread_mutex_t &mutex)//解锁
    {
        pthread_mutex_unlock(&mutex);
    }
public:
    RingQueue(int cap)
        :_rq(cap)
        ,_cap(cap)
        ,_productor_step(0)
        ,_consumer_step(0)
    {
        sem_init(&_room_sem,0,_cap);
        sem_init(&_data_sem,0,0);
        pthread_mutex_init(&_productor_mutex,nullptr);
        pthread_mutex_init(&_consumer_mutex,nullptr);
    }


    void Enqueue(const T&in)
    {
        P(_room_sem);
        Lock(_productor_mutex);
        //开始生产
        _rq[_productor_step] = in;
        _productor_step++;
        _productor_step %= _cap;//环形队列

        UnLock(_productor_mutex);
        V(_data_sem);
    }

    void Pop(T *out)
    {
        P(_data_sem);

        Lock(_consumer_mutex);
        //消费
        *out = _rq[_consumer_step];
        _consumer_step++;
        _consumer_step%=_cap;

        UnLock(_consumer_mutex);

        V(_room_sem);
    }

    ~RingQueue()
    {
        sem_destroy(&_room_sem);
        sem_destroy(&_data_sem);
        pthread_mutex_destroy(&_productor_mutex);
        pthread_mutex_destroy(&_consumer_mutex);
    }
private:
    std::vector<T> _rq;
    int _cap;
    int _productor_step;//生产者步数
    int _consumer_step;//消费者步数
    //定义信号量
    sem_t _room_sem;//空间信号量，生产者关心
    sem_t _data_sem;//数据信号量，消费者关心
    //锁
    pthread_mutex_t _productor_mutex;
    pthread_mutex_t _consumer_mutex;
};